﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Linq;
using System.Data.SqlClient;
using System.Text;
using IntraVision.Web;
using IntraVision.Web.Toolkit;

public class ReportController<TDataContext> : ControllerBase
    where TDataContext : DataContext, new()
{
    protected bool _isExcel = false;
    protected string _CommandName;
    protected CommandType _CommandType;
    protected Dictionary<string, object> _CommandParams;
    protected string[] _ColumnsCaptions;
    protected bool _isCalculateTotal = true;

    public ReportController():base()
    {
        _CommandName = String.Format("up_{0}", Name);
        _CommandType = CommandType.StoredProcedure;
        _CommandParams = new Dictionary<string, object>();

        RegisterStylesheet("report.css");
    }

    public virtual void Default()
    {
        if (string.IsNullOrEmpty(TemplatePath)) TemplatePath = "~/views/" + Name + "/list.haml";
        if (string.IsNullOrEmpty(LayoutPath) && string.IsNullOrEmpty(Request["nolayout"])) LayoutPath = "~/views/layouts/page.haml";

        using (TDataContext dc = new TDataContext())
        {
            GetData(dc);
        }

        RegisterScript("report/report.js");

        RenderView();
    }

    public void Excel()
    {
        TemplatePath = "~/views/_table/reporttableexcel.haml";
        LayoutPath = "~/views/layouts/excelpage.haml";

        Response.ContentType = "application/vnd.ms-excel";
        Response.AppendHeader("Content-Disposition", "attachment;filename=export.xls");

        ViewData["excel"] = _isExcel = true;

        Default();
    }


    protected virtual void InitParams(TDataContext dc) { }

    protected virtual void GetData(TDataContext dc)
    {     
        InitParams(dc);

        var cn = dc.Connection as SqlConnection;
        var cmd = new SqlCommand(_CommandName, cn);
        cmd.CommandType = _CommandType;

        //добавляем параметры для команды, если таковые есть
        foreach (var key in _CommandParams.Keys)
            cmd.Parameters.AddWithValue(key, _CommandParams[key]);

        //получаем данные
        using (var ds = new DataSet())
        {
            var da = new SqlDataAdapter(cmd);
            try
            {
                da.Fill(ds);
            }
            catch (SqlException ex)
            {
                ViewData.Exceptions.Add(SqlExceptionHelper.WrapException(ex));
            }
            catch (Exception ex)
            {
                ViewData.Exceptions.Add(ex);
            }
            finally
            {
                da.Dispose();
            }

            DataReceived(ds);
        }
    }

    protected virtual void DataReceived(DataSet ds)
    {
        var dt = new DataTable();
        if (ds.Tables.Count > 0)
        {
            dt = ds.Tables[0];

            PrepareDataTable(ref dt);

            if (_isCalculateTotal)
                ViewData["total"] = CalculateTotal(dt);
        }
        ViewData["DataTable"] = dt;
    }

    protected virtual void PrepareDataTable(ref DataTable dt)
    {
        SetColumnsCaption(ref dt);
        return;
    }

    protected void SetColumnsCaption(ref DataTable dt)
    {
        if (_ColumnsCaptions != null && dt.Columns.Count == _ColumnsCaptions.Length)
            for (int i = 0; i < dt.Columns.Count; i++)
                dt.Columns[i].Caption = _ColumnsCaptions[i];
    }

    protected virtual Dictionary<string, decimal> CalculateTotal(DataTable dt)
    {
        //Подсчет итогов
        Dictionary<string, decimal> total = new Dictionary<string, decimal>();

        foreach (DataColumn dc in dt.Columns)
        {
            if (dc.DataType == typeof(decimal))
            {
                decimal t = 0;
                foreach (DataRow dr in dt.Rows)
                    t += Convert.ToDecimal(dr[dc]);
                total[dc.ColumnName] = t;
            }
            else
                total[dc.ColumnName] = -1;
        }

        return total;
    }


    protected object GetMonthList()
    {
        int count = 12;
        List<object> monthsList = new List<object>(count);
        for (int i = 0; i < count; i++)
            monthsList.Add(new { id = i + 1, name = (DateTime.MinValue.AddMonths(i)).ToString("MMMM") });
        return monthsList;
    }

    protected object GetYearsList(int lastYear, int count)
    {
        List<object> yearList = new List<object>(count + 1);
        for (int i = lastYear; i >= lastYear - count; i--)
            yearList.Add(new { id = i, name = i.ToString() });
        return yearList;
    }
}
